package hw03;

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class FunctionalDependency implements Dependency, Comparable<FunctionalDependency> {
	
	private Set<Attribute> left;
	private Set<Attribute> right;

	public FunctionalDependency(Set<Attribute> left, Attribute right) {
		this.left = left;
		this.right = new TreeSet<Attribute>();
		this.right.add(right);
	}

	public FunctionalDependency(Set<Attribute> left, Set<Attribute> right) {
		this.left = left;
		this.right = right;
	}
	
	public Set<Attribute> getLeft() {
		return left;
	}

	public Set<Attribute> getRight() {
		return right;
	}
	
	@Override
	public String toString() {
		String toString = "";
		Iterator<Attribute> leftIter = new TreeSet<Attribute>(getLeft()).iterator();
		while(leftIter.hasNext()) {
			toString += leftIter.next();
			if(leftIter.hasNext()) {
				toString += ", ";
			}
		}
		toString += " -> ";
		Iterator<Attribute> rightIter = new TreeSet<Attribute>(getRight()).iterator();
		while(rightIter.hasNext()) {
			toString += rightIter.next();
			if(rightIter.hasNext()) {
				toString += ", ";
			}
		}
		return toString + ";";
	}

	public static FunctionalDependency parse(String statement, Schema schema) {
		try {
			String[] components = statement.split("->");
			Set<Attribute> left = Attribute.parseSet(components[0], schema);					
			Set<Attribute> right = Attribute.parseSet(components[1], schema);
			return new FunctionalDependency(left, right);
		} catch(Exception e) {}
		return null;
	}

	@Override
	public int compareTo(FunctionalDependency o) {
		return toString().compareTo(o.toString());
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof FunctionalDependency) {
			FunctionalDependency o = (FunctionalDependency) obj;
			return o.getLeft().equals(o.getLeft()) && getRight().equals(o.getRight());
		}
		return super.equals(obj);
	}
	
	public boolean followsFrom(Set<FunctionalDependency> S) {
		return Utils.closure(getLeft(), S).containsAll(getRight());
	}
	
	public Set<FunctionalDependency> split() {
		Set<FunctionalDependency> split = new TreeSet<FunctionalDependency>();
		for(Attribute a : getRight()) {
			split.add(new FunctionalDependency(new TreeSet<Attribute>(getLeft()), a));
		}
		return split;
	}

}
